package com.deep.bilibili.util;


import com.deep.bilibili.exception.UploadException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.net.MalformedURLException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;


public class UploadUtil {
    private static final Logger logger = LoggerFactory.getLogger(UploadUtil.class);

    /**
     * 存储文件到系统
     *
     * @param file 文件
     * @return 文件名
     */
    public static String storeFile(Path fileStorageLocation, MultipartFile file) {
        // Normalize file name
        String fileName = StringUtils.cleanPath(file.getOriginalFilename());
        logger.info(fileName);

        try {
            // Check if the file's name contains invalid characters
            if (fileName.contains("..")) {
                throw new UploadException("504", "文件名包含无效的路径序列 " + fileName);
            }

            // Copy file to the target location (Replacing existing file with the same name)
            Path targetLocation = fileStorageLocation.resolve(fileName);

            logger.info(targetLocation.toString());

            Files.copy(file.getInputStream(), targetLocation, StandardCopyOption.REPLACE_EXISTING);

            return fileName;
        } catch (IOException ex) {
            throw new UploadException("501", "无法存储文件 " + fileName + " ", ex);
        }
    }

    /**
     * @param fileStorageLocation
     * @param filePath
     * @param file
     * @return
     */
    public static String storeFile(Path fileStorageLocation, String filePath, MultipartFile file) {
        // Normalize file name
        String fileName = StringUtils.cleanPath(file.getOriginalFilename());
        logger.debug(fileName);

        String newFileName = "";

        try {
            // Check if the file's name contains invalid characters
            if (fileName.contains("..")) {
                throw new UploadException("503", "文件名包含无效的路径序列： " + fileName);
            }

            // Copy file to the target location (Replacing existing file with the same name)
            Path savePath = fileStorageLocation.resolve(filePath);

            isChartPathExist(savePath.toString());

            String targetFilePath = filePath + File.separator + fileName;

            logger.debug(targetFilePath);

            Path targetLocation = fileStorageLocation.resolve(targetFilePath);

            logger.debug(targetLocation.toString());

            Files.copy(file.getInputStream(), targetLocation, StandardCopyOption.REPLACE_EXISTING);

            return targetFilePath;
        } catch (IOException ex) {

            throw new UploadException("501", "无法存储文件： " + fileName + "", ex);
        }
    }

    /**
     * @param fileStorageLocation
     * @param filePath
     * @param fileName
     * @param file
     * @return
     */
    public static String storeFile(Path fileStorageLocation, String filePath, String fileName, MultipartFile file) {

        try {

            // Copy file to the target location (Replacing existing file with the same name)
            Path savePath = fileStorageLocation.resolve(filePath);

            isChartPathExist(savePath.toString());

            String targetFilePath = filePath + File.separator + fileName;

            logger.debug(targetFilePath);

            Path targetLocation = fileStorageLocation.resolve(targetFilePath);

            logger.debug(targetLocation.toString());

            Files.copy(file.getInputStream(), targetLocation, StandardCopyOption.REPLACE_EXISTING);

            return targetFilePath;
        } catch (IOException ex) {

            throw new UploadException("501", "无法存储文件： " + fileName + "", ex);
        }
    }

    /**
     * 加载文件
     *
     * @param fileName 文件名
     * @return 文件
     */
    public static Resource loadFileAsResource(Path fileStorageLocation, String fileName) {
        try {
            Path filePath = fileStorageLocation.resolve(fileName).normalize();
            Resource resource = new UrlResource(filePath.toUri());
            if (resource.exists()) {
                return resource;
            } else {
                throw new UploadException("File not found " + fileName);
            }
        } catch (MalformedURLException ex) {
            throw new UploadException("File not found " + fileName, ex);
        }
    }


    public static void isChartPathExist(String dirPath) {
        File file = new File(dirPath);
        if (!file.exists()) {
            file.mkdirs();
        }
    }

    public static String bytes2kb(BigDecimal filesize) {
//        BigDecimal filesize = new BigDecimal(bytes);
        BigDecimal gibibyte = new BigDecimal(1024 * 1024 * 1024);
        float returnValue = filesize.divide(gibibyte, 2, BigDecimal.ROUND_UP).floatValue();
        /*divide(BigDecimal divisor, int scale, int roundingMode) 返回一个BigDecimal，其值为（this/divisor），其标度为指定标度*/
        if (returnValue > 10) {
            return (returnValue + "GB");
        } else {
            BigDecimal mebibyte = new BigDecimal(1024 * 1024);
            returnValue = filesize.divide(mebibyte, 2, BigDecimal.ROUND_UP).floatValue();
            if (returnValue > 1) {
                return (returnValue + "MB");
            } else {
                BigDecimal kibibyte = new BigDecimal(1024);
                returnValue = filesize.divide(kibibyte, 2, BigDecimal.ROUND_UP).floatValue();
                return (returnValue + "KB");
            }
        }
    }

    public static String getPrintSize(BigDecimal size) {
        // 如果字节数少于1024，则直接以B为单位，否则先除于1024，后3位因太少无意义
        double value = size.doubleValue();
        if (value < 1024) {
            return String.valueOf(value) + "B";
        } else {
            value = new BigDecimal(value / 1024).setScale(2, BigDecimal.ROUND_DOWN).doubleValue();
        }
        // 如果原字节数除于1024之后，少于1024，则可以直接以KB作为单位
        // 因为还没有到达要使用另一个单位的时候
        // 接下去以此类推
        if (value < 1024) {
            return String.valueOf(value) + "KB";
        } else {
            value = new BigDecimal(value / 1024).setScale(2, BigDecimal.ROUND_DOWN).doubleValue();
        }
        if (value < 1024) {
            return String.valueOf(value) + "MB";
        } else {
            // 否则如果要以GB为单位的，先除于1024再作同样的处理
            value = new BigDecimal(value / 1024).setScale(2, BigDecimal.ROUND_DOWN).doubleValue();
            return String.valueOf(value) + "GB";
        }
    }

    /**
     * 判断文件大小
     *
     * @param len  文件长度
     * @param size 限制大小
     * @param unit 限制单位（B,K,M,G）
     * @return
     */
    public static boolean checkFileSize(Long len, int size, String unit) {
//        long len = file.length();
        double fileSize = 0;
        if ("B".equals(unit.toUpperCase())) {
            fileSize = (double) len;
        } else if ("K".equals(unit.toUpperCase())) {
            fileSize = (double) len / 1024;
        } else if ("M".equals(unit.toUpperCase())) {
            fileSize = (double) len / 1048576;
        } else if ("G".equals(unit.toUpperCase())) {
            fileSize = (double) len / 1073741824;
        }
        if (fileSize > size) {
            return true;
        }
        return false;
    }

    public static String getExtFromPath(String inputPath) {
        String type = inputPath.substring(inputPath.lastIndexOf(".") + 1, inputPath.length()).toLowerCase();
        return type;
    }


    public static boolean checkFile(String path) {
        File file = new File(path);
        if (!file.isFile()) {
            return false;
        }
        return true;
    }


    public static int checkContentType(String inputPath) {
        String type = getExtFromPath(inputPath);
        // ffmpeg能解析的格式：（asx，asf，mpg，wmv，3gp，mp4，mov，avi，flv等）
        if (type.equals("avi")) {
            return 1;
        } else if (type.equals("mpg")) {
            return 1;
        } else if (type.equals("wmv")) {
            return 1;
        } else if (type.equals("3gp")) {
            return 1;
        } else if (type.equals("mov")) {
            return 1;
        } else if (type.equals("mp4")) {
            return 1;
        } else if (type.equals("mkv")) {
            return 1;
        } else if (type.equals("asf")) {
            return 0;
        } else if (type.equals("flv")) {
            return 0;
        } else if (type.equals("rm")) {
            return 0;
        } else if (type.equals("rmvb")) {
            return 1;
        }
        return 9;
    }

}
